import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'
import { AnyMap, ArrayUtils } from 'monk-design/utils'
import { AdBreadcrumbNode, AdBreadcrumbNodeImpl } from './breadcrumb.node'

export type AdBreadcrumbEventTarget = 'goBack' | 'click'

export interface AdBreadcrumbClickOptions<T extends AdBreadcrumbNode = AdBreadcrumbNode> {
  node: T
  nodes: T[]
  instance: AdBreadcrumbComponent<T>
  ids: string
  target: AdBreadcrumbEventTarget
}

@Component({
  selector: 'ad-breadcrumb',
  templateUrl: './breadcrumb.component.html',
  host: {
    class: 'ad-breadcrumb',
  },
})
export class AdBreadcrumbComponent<T extends AdBreadcrumbNode> implements OnChanges {
  /**
   * 分割字符
   */
  @Input() dividerChar: String = '/'
  @Input() nodes: (T | string | AnyMap)[] = []
  breadcrumbList: T[] = []
  @Output() goBack: EventEmitter<void> = new EventEmitter()
  @Output() clickNode: EventEmitter<AdBreadcrumbClickOptions<T>> = new EventEmitter()
  ngOnChanges(changes: SimpleChanges): void {
    if (changes.nodes) {
      if (Array.isArray(this.nodes)) {
        this.breadcrumbList = this.nodes
          .filter(Boolean)
          .map((node): T => {
            if (node instanceof AdBreadcrumbNodeImpl) {
              return node as unknown as T
            } else if (typeof node === 'string') {
              return new AdBreadcrumbNodeImpl()
                .set('name', node)
                .set('disabled', true) as unknown as T
            } else {
              return new AdBreadcrumbNodeImpl().copyProperty(node) as unknown as T
            }
          })
          .filter((node) => !node.hidden)
      } else {
        this.breadcrumbList = []
      }
    }
  }

  /**
   * 处理节点点击事件
   * @param node
   */
  clickNodeHandle(node: T, target: AdBreadcrumbEventTarget = 'click') {
    const endIndex = node.id ? this.breadcrumbList.findIndex((item) => item == node) : -1
    const range = this.breadcrumbList.slice(0, endIndex + 1).filter((node) => Boolean(node.id))
    this.clickNode.emit({
      node,
      nodes: this.breadcrumbList,
      instance: this,
      ids: range.map((node) => node.id).join('*'),
      target,
    })
  }

  get goBackIsDisabled() {
    if (this.goBack.observers.length > 0) {
      return false
    }
    const breadcrumbList = this.breadcrumbList.filter((node) => node.disabled !== true)
    if (breadcrumbList.length >= 1 && breadcrumbList[0] !== ArrayUtils.last(this.breadcrumbList)) {
      return false
    }
    return true
  }

  goBackHandle() {
    let lastNotDisabledNode
    for (let i = this.breadcrumbList.length - 1; i >= 0; i--) {
      const node = this.breadcrumbList[i]
      if (node !== ArrayUtils.last(this.breadcrumbList) && node.disabled !== true) {
        lastNotDisabledNode = node
        break
      }
    }
    if (lastNotDisabledNode) {
      this.clickNodeHandle(lastNotDisabledNode, 'goBack')
    } else {
      this.goBack.emit()
    }
  }
}
